/* ==========================================================
File:        ConfigFile.java
Description: Read and write settings from the INI config file.
Maintainer:  WakaTime <support@wakatime.com>
License:     BSD, see LICENSE for more details.
Website:     https://wakatime.com/
===========================================================*/

package com.wakatime.intellij.plugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

public class ConfigFile {
    private static final String fileName = ".wakatime.cfg";
    private static final String internalFileName = "wakatime-internal.cfg";
    private static String cachedHomeFolder = null;
    private static String _api_key = "";
    private static boolean _usingVaultCmd = false;

    /**
     * 找到用户的主目录，后面拼上.wakatime.cfg，作为插件的配置文件的存储文件，并返回该文件的完整路径名
     * @param internal
     * @return
     */
    private static String getConfigFilePath(boolean internal) {
        if (ConfigFile.cachedHomeFolder == null) {
            if (System.getenv("WAKATIME_HOME") != null && !System.getenv("WAKATIME_HOME").trim().isEmpty()) {
                File folder = new File(System.getenv("WAKATIME_HOME"));
                if (folder.exists()) {
                    ConfigFile.cachedHomeFolder = folder.getAbsolutePath();
                    WakaTime.log.debug("Using $WAKATIME_HOME for config folder: " + ConfigFile.cachedHomeFolder);
                    if (internal) {
                        return new File(new File(ConfigFile.cachedHomeFolder, ".wakatime"), internalFileName).getAbsolutePath();
                    }
                    return new File(ConfigFile.cachedHomeFolder, fileName).getAbsolutePath();
                }
            }
            // 通过System.getProperty("user.home")获取到用户的主目录(即~)，并返回其绝对路径
            ConfigFile.cachedHomeFolder = new File(System.getProperty("user.home")).getAbsolutePath();
            WakaTime.log.debug("Using $HOME for config folder: " + ConfigFile.cachedHomeFolder);
        }
        if (internal) {
            return new File(new File(ConfigFile.cachedHomeFolder, ".wakatime"), internalFileName).getAbsolutePath();
        }
        return new File(ConfigFile.cachedHomeFolder, fileName).getAbsolutePath();
    }

    /**
     * 从插件配置文件~/.wakatime.cfg中，查找指定key在文件中配置的对应的值返回。比如文件内容如下：
     * [settings]
     * api_key = waka_e2975c29-5d40-4022-bcea-04d83634c230
     * proxy =
     * debug = false
     * status_bar_enabled = true
     *
     * 则key传debug时，函数会返回false
     * @param section
     * @param key
     * @param internal
     * @return
     */
    public static String get(String section, String key, boolean internal) {
        // 获取插件配置文件的完整路径名字，即~/.wakatime.cfg
        String file = ConfigFile.getConfigFilePath(internal);
        String val = null;
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String currentSection = "";
            try {
                String line = br.readLine();
                while (line != null) {
                    if (line.trim().startsWith("[") && line.trim().endsWith("]")) {
                        currentSection = line.trim().substring(1, line.trim().length() - 1).toLowerCase();
                    } else {
                        if (section.toLowerCase().equals(currentSection)) {
                            String[] parts = line.split("=");
                            if (parts.length == 2 && parts[0].trim().equals(key)) {
                                val = parts[1].trim();
                                br.close();
                                return removeNulls(val);
                            }
                        }
                    }
                    line = br.readLine();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e1) { /* ignored */ }
        return removeNulls(val);
    }

    /**
     * 将键值对[key, val]写入到~/.wakatime.cfg的相应的section栏中，如key=debug, val=true，section=settings，则
     *      * [settings]
     *      * api_key = waka_e2975c29-5d40-4022-bcea-04d83634c230
     *      * proxy =
     *      * debug = false
     *      * status_bar_enabled = true
     *      *
     * @param section
     * @param key
     * @param internal
     * @param val
     */
    public static void set(String section, String key, boolean internal, String val) {
        key = removeNulls(key);
        val = removeNulls(val);

        String file = ConfigFile.getConfigFilePath(internal);
        StringBuilder contents = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            try {
                String currentSection = "";
                String line = br.readLine();
                Boolean found = false;
                while (line != null) {
                    line = removeNulls(line);
                    if (line.trim().startsWith("[") && line.trim().endsWith("]")) {
                        if (section.toLowerCase().equals(currentSection) && !found) {
                            contents.append(key + " = " + val + "\n");
                            found = true;
                        }
                        currentSection = line.trim().substring(1, line.trim().length() - 1).toLowerCase();
                        contents.append(line + "\n");
                    } else {
                        if (section.toLowerCase().equals(currentSection)) {
                            String[] parts = line.split("=");
                            String currentKey = parts[0].trim();
                            if (currentKey.equals(key)) {
                                if (!found) {
                                    contents.append(key + " = " + val + "\n");
                                    found = true;
                                }
                            } else {
                                contents.append(line + "\n");
                            }
                        } else {
                            contents.append(line + "\n");
                        }
                    }
                    line = br.readLine();
                }
                if (!found) {
                    if (!section.toLowerCase().equals(currentSection)) {
                        contents.append("[" + section.toLowerCase() + "]\n");
                    }
                    contents.append(key + " = " + val + "\n");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e1) {

            // cannot read config file, so create it
            contents = new StringBuilder();
            contents.append("[" + section.toLowerCase() + "]\n");
            contents.append(key + " = " + val + "\n");
        }

        PrintWriter writer = null;
        try {
            writer = new PrintWriter(file, "UTF-8");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        if (writer != null) {
            writer.print(contents.toString());
            writer.close();
        }
    }

    public static String getApiKey() {
        if (ConfigFile._usingVaultCmd) {
            return "";
        }
        if (!ConfigFile._api_key.equals("")) {
            return ConfigFile._api_key;
        }

        String apiKey = get("settings", "api_key", false);
        if (apiKey == null) {
            String vaultCmd = get("settings", "api_key_vault_cmd", false);
            if (vaultCmd != null && !vaultCmd.trim().equals("")) {
                ConfigFile._usingVaultCmd = true;
                return "";
            }
            apiKey = "";
        }

        ConfigFile._api_key = apiKey;
        return apiKey;
    }

    public static boolean usingVaultCmd() {
        return ConfigFile._usingVaultCmd;
    }

    public static void setApiKey(String apiKey) {
        set("settings", "api_key", false, apiKey);
        ConfigFile._api_key = apiKey;
    }

    private static String removeNulls(String s) {
        if (s == null) return null;
        return s.replace("\0", "");
    }

}
